﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
using System.Xml.Xsl;

class Catalog
{
    //2
    public static void ShowArtists(string fileName)
    {
        XmlDocument doc = new XmlDocument();
        doc.Load(fileName);
        Dictionary<string, int> artists = new Dictionary<string, int>();
        XmlNode rootNode = doc.DocumentElement;
        foreach (XmlNode node in rootNode.ChildNodes)
        {
            string artist = node["artist"].InnerText;
            if (artists.ContainsKey(artist))
            {
                artists[artist]++;
            }
            else
            {
                artists.Add(artist, 1);
            }
        }
        foreach (var item in artists)
        {
            Console.WriteLine("Artist: {0} - numbers of albums: {1}",item.Key,item.Value);
        }
    }

    //3
    public static void ShowArtistsWithXPath(string fileName)
    {
        XmlDocument doc = new XmlDocument();
        doc.Load(fileName);
        string xPathQuery = @"/albums/album/artist";
        XmlNodeList artistsList = doc.SelectNodes(xPathQuery);
        Dictionary<string, int> artists = new Dictionary<string, int>();
        foreach (XmlNode item in artistsList)
        {
            if (artists.ContainsKey(item.InnerText))
            {
                artists[item.InnerText]++;
            }
            else
            {
                artists.Add(item.InnerText, 1);
            }
        }
        foreach (var item in artists)
        {
            Console.WriteLine("Artist: {0} - numbers of albums: {1}", item.Key, item.Value);
        }
    }

    //4
    public static void DeleteAlbums(string fileName, decimal price)
    {
        //s edin foreach kato predi da iztriem tekyshtiq current stava next i triem previous, ako nqma next triem curr ;)
        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.Load(fileName);
        XmlNode rootNode = xmlDoc.DocumentElement;
        List<XmlNode> nodesToDelete = new List<XmlNode>();
        foreach (XmlNode node in rootNode.ChildNodes)
        {
            string currentPrice = node["price"].InnerText;
            if (decimal.Parse(currentPrice) > price)
            {
                nodesToDelete.Add(node);
            }            
        }        
        foreach (XmlNode item in nodesToDelete)
        {
            rootNode.RemoveChild(item);
            Console.WriteLine("Album {0} deleted!",item["name"].InnerText);
        }
        xmlDoc.Save("../../catalog-new.xml");
        
    }

    //5
    public static void AllSongs(string fileName)
    {        
        using (XmlReader reader = XmlReader.Create(fileName))
        {
            while (reader.Read())
            {
                if ((reader.NodeType == XmlNodeType.Element) && (reader.Name == "title"))
                {
                    Console.WriteLine(reader.ReadElementString());
                }
            }
        }        
    }

    //6
    public static void AllSongsLinq(string fileName)
    {
        XDocument xmlDoc = XDocument.Load(fileName);

        var songs =
            from song in xmlDoc.Descendants("song")
            select song.Element("title").Value;
        foreach (var item in songs)
        {
            Console.WriteLine(item);
        }
    }

    //7
    public static void CreateXML(string fileSource)
    {
        XmlDocument xmlDoc = new XmlDocument();

        // Write down the XML declaration

        XmlDeclaration xmlDeclaration = xmlDoc.CreateXmlDeclaration("1.0", "utf-8", null);

        // Create the root element
        XmlElement rootNode = xmlDoc.CreateElement("Persons");        
        xmlDoc.InsertBefore(xmlDeclaration, xmlDoc.DocumentElement);
        xmlDoc.AppendChild(rootNode);

        using (TextReader reader = new StreamReader(fileSource))
        {
            while (reader.Peek() > 0)
            {
                // Create a new <Category> element and add it to the root node
                XmlElement parentNode = xmlDoc.CreateElement("Person");
                xmlDoc.DocumentElement.PrependChild(parentNode);

                string[] personInfo = reader.ReadLine().Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                string name = personInfo[0];
                string address = personInfo[1];
                string phone = personInfo[2];
                // Create the required nodes                
                XmlElement nameNode = xmlDoc.CreateElement("Name");
                XmlElement addressNode = xmlDoc.CreateElement("Address");
                XmlElement phoneNode = xmlDoc.CreateElement("Phone");

                // retrieve the text 
                XmlText nameText = xmlDoc.CreateTextNode(name);
                XmlText addressText = xmlDoc.CreateTextNode(address);
                XmlText phoneText = xmlDoc.CreateTextNode(phone);

                // append the nodes to the parentNode without the value
                parentNode.AppendChild(nameNode);
                parentNode.AppendChild(addressNode);
                parentNode.AppendChild(phoneNode);

                // save the value of the fields into the nodes
                nameNode.AppendChild(nameText);
                addressNode.AppendChild(addressText);
                phoneNode.AppendChild(phoneText);
            }
        }

        // Save to the XML file
        xmlDoc.Save("persons.xml");
    }
    
    //8
    public static void Albums(string fileSource)
    {
        XmlReader reader = XmlReader.Create(fileSource);
        using (reader)
        {            
            XmlTextWriter writer = new XmlTextWriter("../../albums.xml", Encoding.UTF8);
            using (writer)
            {
                writer.Formatting = Formatting.Indented;
                writer.IndentChar = '\t';
                writer.Indentation = 1;

                writer.WriteStartDocument();
                writer.WriteStartElement("albums");
                while (reader.Read())
                {
                    if ((reader.NodeType == XmlNodeType.Element) && (reader.Name == "name"))
                    {
                        string name = reader.ReadElementString();
                        reader.Read();
                        string author = reader.ReadElementString();
                        writer.WriteStartElement("album");
                        writer.WriteAttributeString("author", author);
                        writer.WriteValue(name);
                        writer.WriteEndElement();
                    }
                }
                writer.WriteEndElement();
                writer.WriteEndDocument();
            }            
        }
    }

    //9
    public static void FileSystem(string directory)
    {
        DirectoryInfo dir = new DirectoryInfo(directory);
        XmlTextWriter writer = new XmlTextWriter("f:\\dirs.xml", Encoding.GetEncoding("windows-1252"));
        //writer.WriteStartDocument
        using (writer)
        {
            writer.Formatting = Formatting.Indented;
            writer.IndentChar = '\t';
            writer.Indentation = 1;

            writer.WriteStartDocument();

            WriteDir(dir, writer);

            writer.WriteEndDocument();
        }
    }

    public static void WriteDir(DirectoryInfo dir, XmlTextWriter writer)
    {
        writer.WriteStartElement("dir");
        writer.WriteAttributeString("Name", dir.Name);
        foreach (var item in dir.GetFiles())
        {
            writer.WriteStartElement("file");
            writer.WriteAttributeString("name",item.Name);
            writer.WriteAttributeString("Extension", item.Extension);
            writer.WriteEndElement();
        }        

        foreach (var item in dir.GetDirectories())
        {
            WriteDir(item, writer);
            writer.WriteEndElement();
        }
        
    }

    //10
    public static void FileSystemLinq(string directory)
    {
        DirectoryInfo dir = new DirectoryInfo(directory);
        XDocument xdoc = new XDocument(new XDeclaration("1.0", "utf-8", null),new XElement("asd"));
        WriteDirX(dir, xdoc.Root);
        xdoc.Save("F:\\dirsX.xml");
    }

    public static void WriteDirX(DirectoryInfo dir, XElement xdoc)
    {
        XElement d = new XElement("dir", new XAttribute("name", dir.Name));
        xdoc.Add(d);
        foreach (FileInfo item in dir.GetFiles())
        {
            xdoc.Add(new XElement("file",new XAttribute("name", item.Name), new XAttribute("extention",item.Extension)));
        }
        foreach (DirectoryInfo item in dir.GetDirectories())
        {
            WriteDirX(item, d);
        }
    }

    //11
    public static void AlbumsBefore(string fileName)
    {
        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.Load(fileName);
        string xPathQuery = String.Format("/albums/album[({0} - year) >= 5]/price",DateTime.Now.Year);
        XmlNodeList prices = xmlDoc.SelectNodes(xPathQuery);
        foreach (XmlNode item in prices)
        {
            Console.WriteLine(item.InnerText);
        }
        Console.WriteLine();

        XDocument xDoc = XDocument.Load(fileName);
        var pricesX =
            from album in xDoc.Descendants("album")
            where (DateTime.Now.Year - int.Parse(album.Element("year").Value)) >= 5
            select album.Element("price").Value;
        foreach (string item in pricesX)
        {
            Console.WriteLine(item);
        }
    }

    //12 & 13
    public static void TransformIntoHtml(string fileName)
    {
        FileInfo file = new FileInfo(fileName);
        XslCompiledTransform xslt = new XslCompiledTransform();
        xslt.Load(fileName);
        xslt.Transform("../../catalog.xml","../../catalog.html");
    }

    static void Main()
    {
        //ShowArtists("../../catalog.xml");
        //Console.WriteLine();
        //ShowArtistsWithXPath("../../catalog.xml");
        //Console.WriteLine();
        //DeleteAlbums("../../catalog.xml",20m);
        //Console.WriteLine();
        //AllSongs("../../catalog.xml");
        //Console.WriteLine();
        //AllSongsLinq("../../catalog.xml");
        //Console.WriteLine();
        //CreateXML("persons.txt");
        //Console.WriteLine();
        //Albums("../../catalog.xml");
        //Console.WriteLine();
        //FileSystem(@"f:\Movies");
        //FileSystemLinq(@"F:\Movies");
        //AlbumsBefore("../../catalog.xml");
        //TransformIntoHtml("../../catalog.xslt");
    }
}
